using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;
using BTreeSharp;
using BTreeSharp.Surfaces;
using System.IO;

namespace TheTest
{
    

    [TestFixture]
    public class InMemorySurfaceTest
    {
        Surface surface;
        
        public void SetupSurface()
        {
            surface = new InMemorySurface();
            surface.AllocateSpace(1000);
        }
        [Test]
        [ExpectedException(typeof(InvalidOperationException))]
        public void AllocateSpaceLength()
        {
            InMemorySurface surface = new InMemorySurface();
            surface.AllocateSpace(1000);
            Assert.AreEqual(1000, surface.Length);
            surface.AllocateSpace(100);//throw invalid operation
        }
        [Test]
        public void ReadWriteBytes()
        {
            SetupSurface();
            surface.Seek(0, System.IO.SeekOrigin.Begin);
            surface.WriteBytes(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 });
            surface.Seek(0, System.IO.SeekOrigin.Begin);
            byte[] check = surface.ReadBytes(8);
            Assert.AreEqual(8, check.Length);
            for (byte b = 1; b <= 8; ++b)
            {
                Assert.AreEqual(b,check[b - 1]);
            }
        }
        [Test]
        public void Position()
        {
            SetupSurface();
            surface.WriteBytes(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 });
            Assert.AreEqual(8, surface.Position);
        }
        [Test]
        [ExpectedException(typeof(IndexOutOfRangeException))]
        public void OutOfBound()
        {
            SetupSurface();
            surface.Seek(surface.Length - 1, SeekOrigin.Begin);
            surface.WriteBytes(new byte[]{0,0});
        }
        [Test]
        public void Realloc()
        {
            SetupSurface();
            surface.Seek(surface.Length-8-1, System.IO.SeekOrigin.Begin);
            surface.WriteBytes(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 });
            long prevPos = surface.Position;
            long prevLength = surface.Length;
            Assert.AreEqual(surface.Length - 1, prevPos);
            surface.ReallocateSpace(surface.Length * 2);
            Assert.AreEqual(prevPos, surface.Position);
            Assert.AreEqual(2 * prevLength, surface.Length);
            surface.WriteBytes(new byte[] { 9, 10, 11, 12, 13, 14, 15, 16 });
            surface.Seek(-16, SeekOrigin.Current);
            byte[] check = surface.ReadBytes(16);
            for (byte b = 1; b <= 16; ++b)
            {
                Assert.AreEqual(b, check[b - 1]);
            }

        }
        [Test]
        public void Seek()
        {
            SetupSurface();
            surface.Seek(100, System.IO.SeekOrigin.Begin);
            surface.WriteBytes(new byte[] { 1 });
            surface.Seek(99, System.IO.SeekOrigin.Current);
            surface.WriteBytes(new byte[] { 2 });
            surface.Seek(-1, System.IO.SeekOrigin.End);
            surface.WriteBytes(new byte[] { 3 });
            surface.Seek(100, SeekOrigin.Begin);
            byte[] check = surface.ReadBytes(1);
            Assert.AreEqual(1, check[0]);
            surface.Seek(200, SeekOrigin.Begin);
            check = surface.ReadBytes(1);
            Assert.AreEqual(2, check[0]);
            surface.Seek(surface.Length-2, SeekOrigin.Begin);
            check = surface.ReadBytes(1);
            Assert.AreEqual(3, check[0]);
        }


    }
}
